﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Diagnostics;

namespace CPPEI.Net.TCP
{
    class ReceiveThread
    {
        private Thread _thread;
        private bool _isRunning = false;
        private EventWaitHandle _eventHandle;

        TCPServer _server;

        //private RequestResolver _requestResolver;

        //private RPGHandle _actionDispacher;

        public ReceiveThread(TCPServer server)
        {
            this._server = server;
            //_requestResolver = new RequestResolver();

            //_actionDispacher = new RPGHandle();
        }

        public void Start()
        {
            Console.WriteLine("server start receive");

            this._eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
            this._thread = new Thread(Running);
            this._isRunning = true;
            Console.WriteLine("receive start");
            this._thread.Start();
        }

        public void Stop()
        {
            this._isRunning = false;
            this._eventHandle.WaitOne();
            Console.WriteLine("server stop receive");
        }

        private void Running()
        {
            Console.WriteLine("receive thread start");
            while (_isRunning)
            {
                // client id
                // command
                // mode
                for (int index = 0; index < _server.EndpointCollection.Length; index++)
                {
                    NetClientProxy clientProxy = _server.EndpointCollection[index];
                    if (clientProxy != null && !clientProxy.IsReceiving)
                    {
                        clientProxy.IsReceiving = true;
                        try
                        {
                            clientProxy.Socket.BeginReceive(clientProxy.Buffer, 0, clientProxy.Buffer.Length, SocketFlags.None, new AsyncCallback(OnReceiveCallback), clientProxy);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(string.Format("删除客户端，原因开始接收客户端:{0}数据,出错:{1}", clientProxy.Id, ex));
                            // 移除客户端
                            _server.ClientDisconnected(clientProxy);
                        }
                    }
                }
            }

            this._eventHandle.Set();
            Console.WriteLine("receive thread stop");
        }

        private void OnReceiveCallback(IAsyncResult ar)
        {
            NetClientProxy proxy = ar.AsyncState as NetClientProxy;
            int receiveLength = 0;

            try
            {
                receiveLength = proxy.Socket.EndReceive(ar);
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("删除客户端，原因结束接收客户端:{0}数据,出错:{1}", proxy.Id, ex));
                // 移除客户端
                _server.ClientDisconnected(proxy);

                return;
            }

            //player.ErrorCount = 0;
            if (receiveLength > 0)
            {
                proxy.ErrorCount = 0;
                Debug.WriteLine(string.Format("收到玩家({0})接收到的数据：{1}, first:{2}", proxy.GetNetAddress(), receiveLength, proxy.Buffer[0]));
                proxy.PackagePool.AppendBuffer(proxy.Buffer, receiveLength);

                Package netPackage = proxy.PackagePool.GetNetBuffer();
                if(netPackage != null)
                {
                    Replay(netPackage, proxy);
                }
            }
            else
            {
                Console.WriteLine(string.Format("收到玩家({0})接收到的数据长度为0", proxy.GetNetAddress()));
                // 收到长度为0的数据视为掉线
                proxy.ErrorCount++;
                if (proxy.ErrorCount > 3)
                {
                    // 3次接收到0的数据视为掉线
                    Console.WriteLine(string.Format("收到玩家({0})接收到的数据长度为0，3次接收到0的数据视为掉线", proxy.GetNetAddress()));
                    // 移除客户端
                    _server.ClientDisconnected(proxy);
                }
            }
            proxy.IsReceiving = false;
        }

        private void Replay(Package netPackage, NetClientProxy proxy)
        {
            IRequestHandler handler = _server.RequestFactory.Create(netPackage.Scenario, netPackage.Command);
            handler.Handle(proxy, netPackage);
        }
    }
}
